有朋友問我為什麼我的進度這麼緩慢...
殊不知,我每天都只有一個小時可以做額外自主練習阿QQ
這週接續著做Rooms資料處理的部分囉~
立馬開始!!
首先, 上週漏做了一段xD
RoomCard 有上下外距, 這個一樣是自己算出來的
來加上然後結束它~
<div class="d-flex justify-center roomcardmain">
//RoomCard
</div>
.roomcardmain {
margin-top: 65px;
margin-bottom: 40px;
}
美多了~
接著本週正題開始~
首先看一下 F2E 提供的API, 要先知道它會傳哪些欄位出來給我們接
順帶一提, 要用它的API要先註冊帳號喔!!! 註冊方式也在同個頁面~
API頁面直接滑到最後的 #[GET] 取得所有房型 部分
會看到其中有個 item陣列, 其中包含:
id
: 房間編號, 房間的唯一值, 要取得房間的詳細資訊必須使用它imageUrl
: 圖片網址, 房間的代表圖, 只有一張normalDayPrice
(integer): 平日價格holidayPrice
(integer): 假日價格name
: 房間名稱看完之後應該會發現, 這欄位根本不夠阿
原來剩下的欄位都在另一個API- [GET] 單一房型細節
不過這邊 F2E 的範例就比較簡單, 實際傳回來的欄位多很多
放上我的Postman截圖
其中包含:
id
: 房間編號, 房間的唯一值name
: 房間名稱imageUrl
(array): 圖片網址, 有多張normalDayPrice
(integer): 平日價格holidayPrice
(integer): 假日價格descriptionShort
(object): 房間簡單說明
GuestMin
(integer): 最少人數GuestMax
(integer): 最多人數Bed
(array): 床型Private-Bath
(integer): 推測是浴室數量(?)Footage
(integer): 這個我真的不知道xD, 推測是設計師做的"大小"的欄位description
: 房間詳細說明checkInAndOut
(object): 入住退房時間
checkInEarly
: 最早入住時間checkInLate
: 最晚入住時間checkOut
: 退房時間amenities
(object): 設施設備
Wi-Fi
(boolean): wifi(xD)Breakfast
(boolean): 早餐Mini-Bar
(boolean): 迷你吧(xD)Room-Service
(boolean): 客房服務Television
(boolean): 電視Air-Conditioner
(boolean): 冷氣Refrigerator
(boolean): 冰箱Sofa
(boolean): 沙發Great-View
(boolean): 景觀Smoke-Free
(boolean): 禁止吸菸Child-Friendly
(boolean): 適合兒童Pet-Friendly
(boolean): 可帶寵物有Google翻譯真好
看完之後大致上就可以了解哪個欄位必須放在RoomCard的哪個位置了(吧xD)
接著在開始ajax抓資料之前, 要先來安裝vue版的ajax - axios:
npm install axios
安裝完成之後, 開啟 main.js 引用它:
//main.js
//加這兩行
import axios from 'axios'
Vue.prototype.$http = axios
教學一下使用方式, 在要使用的地方放入以下這段, 把必填資訊(例如method、headers等等)填好就可以囉!!!
this.$http(
{
method: "", //填http傳遞方式 get/post/put...
headers: {}, //F2E的API要求必須填這個, 詳見剛才的API使用方式
url: "", //填目標的網址
}).then((res) => {
//存取成功時做什麼事
}).catch((err) => {
//存取錯誤時做什麼事
});
預計抓資料的流程會是
id
及 imageUrl
傳入 RoomCard
id
取得 單一房型 的詳細資料來呈現所以來開啟久違的 Rooms 吧~
先加上 created hook,準備把[取得 所有房型]的動作
另外 data 裡面可以先加個 item 空陣列, 等等資料取回來要放在這:
export default {
...,
created() {
...
},
data: () => ({
items: [],
}),
};
hook內就可以放剛才的 axios method 囉~ 這裡都假設能正常取得資料(通常都要寫判斷~但是我懶xD):
this.$http({
method: "get",
headers: {
Accept: "application/json",
Authorization:
"Bearer 這邊填你自己的token喔",
},
url: "https://challenge.thef2e.com/api/thef2e2019/stage6/rooms",
})
.then((res) => {
//成功取得資料時, 把items指定給data.items
this.items = res.data.items;
})
.catch((err) => {
console.log(err);
});
完成後可以開啟 chrome 的 Vue工具看看
太蚌了資料都有進來
如此就完成取得房型資料了~
原本的v-for
就可以改掉囉~
<RoomCard class="col-4" v-for="item in items" :key="item.id" />
再把 id 和 imageUrl 傳入 RoomCard :
<RoomCard
class="col-4"
v-for="item in items"
:key="item.id"
:uid="item.id"
:imageUrl="item.imageUrl"
/>
然後 Rooms 繼續封印xD
回到 RoomCard , 要來用 props 接收 Rooms 傳進來的資料
data 加上 room 物件, 等等資料取回來要放在這:
export default {
name: "RoomCard",
props: ["uid", "imageUrl"],
data: () => ({
room: {},
}),
};
接著跟 Step 15 一樣, 加上 created hook, 裡面放 axios method:
created() {
this.$http({
method: "get",
headers: {
Accept: "application/json",
Authorization:
"Bearer 這邊填你自己的token喔",
},
url:
"https://challenge.thef2e.com/api/thef2e2019/stage6/room/" + this.uid,
})
.then((res) => {
//成功取得資料時, 把room指定給data.room
this.room = res.data.room;
})
.catch((err) => {
console.log(err);
});
},
完成後一樣開啟 chrome 的 Vue工具來檢查
資料確實有抓到呢!!!
再來我們就可以一一的把原本在畫面上放的假資料替換掉囉~
這裡沒什麼技巧, 就是慢慢對應替換而已
有一些需要處理的資料, 可以直接在花括號內處理
例如人數:
<div>人數</div>
<div>
<!--如果descriptionShort存在就判斷GuestMax與GuestMin是否相等-->
<!--相等就放其中一個就好, 不相等就放"GuestMin~GuestMax"-->
{{
room.descriptionShort
? room.descriptionShort.GuestMax ===
room.descriptionShort.GuestMin
? room.descriptionShort.GuestMin
: `${room.descriptionShort.GuestMin}~${room.descriptionShort.GuestMax}`
: ""
}}
</div>
或是床:
<div>床</div>
<div>
<!--Array to string中間會自動加逗號-->
{{ room.descriptionShort ? room.descriptionShort.Bed.toString() : "" }}
</div>
也可以寫在 computed 裡面處理, 例如設施設備:
這邊很可惜的是就算用迴圈寫, 還是必須對應中文名稱...勢必要寫一長串code
computed: {
roomAmenities() {
let amenities = [];
if (this.room.amenities) {
//如果設施設備為true就塞到陣列
if (this.room.amenities["Wi-Fi"]) {
amenities.push(" wifi");
}
if (this.room.amenities["Breakfast"]) {
amenities.push(" 早餐");
}
if (this.room.amenities["Mini-Bar"]) {
amenities.push(" 小吧檯");
}
if (this.room.amenities["Room-Service"]) {
amenities.push(" 客房服務");
}
if (this.room.amenities["Television"]) {
amenities.push(" 電視");
}
if (this.room.amenities["Air-Conditioner"]) {
amenities.push(" 冷氣");
}
if (this.room.amenities["Refrigerator"]) {
amenities.push(" 冰箱");
}
if (this.room.amenities["Sofa"]) {
amenities.push(" 沙發");
}
if (this.room.amenities["Great-View"]) {
amenities.push(" 景觀");
}
if (this.room.amenities["Smoke-Free"]) {
amenities.push(" 禁止吸煙");
}
if (this.room.amenities["Child-Friendly"]) {
amenities.push(" 適合兒童");
}
if (this.room.amenities["Pet-Friendly"]) {
amenities.push(" 可帶寵物");
}
}
return amenities.toString();
},
},
有更好解法請留言告訴我
對應完可以看到畫面上已經都是真實資料囉~
首頁就剩[Footer]囉~留給下次吧xD
附上這次進度的雲端壓縮檔, 執行前記得先npm install
有需要改進或是任何意見建議歡迎下面留言~
可以用 hash 去對應你的中文
// 資料來源
const amenities = {
'Wi-Fi': true,
Breakfast: false,
'Mini-Bar': true,
'Room-Service': false,
Television: true,
'Air-Conditioner': true,
Refrigerator: true,
Sofa: true,
'Great-View': true,
'Smoke-Free': true,
'Child-Friendly': true,
'Pet-Friendly': true,
};
// ---
const translate = {
'Wi-Fi': 'wifi',
Breakfast: '早餐',
'Mini-Bar': '迷你吧',
'Room-Service': '客房服務',
Television: '電視',
'Air-Conditioner': '冷氣',
Refrigerator: '冰箱',
Sofa: '沙發',
'Great-View': '景觀',
'Smoke-Free': '禁止吸菸',
'Child-Friendly': '適合兒童',
'Pet-Friendly': '可帶寵物',
};
const amenitiesCn = [];
Object.keys(amenities).forEach((el) => {
if (amenities[el]) {
amenitiesCn.push(translate[el]);
}
});
/*
[
'wifi', '迷你吧',
'電視', '冷氣',
'冰箱', '沙發',
'景觀', '禁止吸菸',
'適合兒童', '可帶寵物'
]
*/
這個方法可以~~~太感謝了
多學了一招 哈哈哈
我改成了這樣~
roomAmenities() {
let amenities = [];
if (this.room.amenities) {
const translate = {
"Wi-Fi": "wifi",
Breakfast: "早餐",
"Mini-Bar": "迷你吧",
"Room-Service": "客房服務",
Television: "電視",
"Air-Conditioner": "冷氣",
Refrigerator: "冰箱",
Sofa: "沙發",
"Great-View": "景觀",
"Smoke-Free": "禁止吸菸",
"Child-Friendly": "適合兒童",
"Pet-Friendly": "可帶寵物",
};
Object.keys(this.room.amenities).forEach((el) => {
if (this.room.amenities[el]) {
amenities.push(` ${translate[el]} `);
}
});
}
return amenities.toString();
},
},